from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import permissions
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from libs.paginations import ListPagination
from images.models import push_log
from .utils.pods_core import ProductionOprationPodsApi
from .models import ProductionDeployRecord
from .serializers import ProductionDeployRecordDetail
from .utils.namespaced_core import ProductionOprateNamespacedApi
from .utils.deployment_core import ProductionOprationDeploymentApi
from .utils.ingress_core import ProductionOprationIngressApi
from .utils.service_core import ProductionOprationServiceApi


class ProductionNamespacedApiView(APIView):
    '''命名空间'''

    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)

    def get(self, request, *args, **kwargs):
        '''获取命名空间列表  传参：{'namespace_name': str}， namespace_name: 命名空间名称'''

        namespace_list = ProductionOprateNamespacedApi().get_namespace_api()
        # 分页
        page_obj = ListPagination()
        results = page_obj.paginate_queryset(queryset=namespace_list, request=request, view=self)

        # 返回带超链接 需返回的时候用内置的响应方法
        return page_obj.get_paginated_response(results)

    def post(self, request, format=None):
        '''创建命名空间  传参：{'namespace_name': str}，  namespace_name: 为需要新建的命名空间名称'''

        namespace_name = self.request.data['namespace_name']
        namespace_obj = ProductionOprateNamespacedApi(namespace=namespace_name)

        return Response(namespace_obj.create_namespace_api())

    def delete(self, request, format=None):
        '''删除命名空间  传参：{'namespace_name': str}，  namespace_name: 为需要新建的命名空间名称'''

        namespace_name = self.request.query_params['namespace_name']
        namespace_obj = ProductionOprateNamespacedApi(namespace=namespace_name)

        return Response(namespace_obj.delete_namespace_api())


class ProductionPodsApiView(APIView):
    '''容器组'''

    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)

    def get(self, request, *args, **kwargs):
        ''' 获取对应命名空间的所有容器组列表，传参：{'namespace_name' : str}   namespace_name: 为需要新建的命名空间名称.\n
            重启单个容器组实例，传参：{'namespace_name' : str, 'pod_name' : str}   pod_name: 为容器组名称.
        '''

        namespace_name = self.request.query_params['namespace_name']
        if len(namespace_name) <= 0:
            return Response({'msg': 'namespace_name为必传参数'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 对单个pod进行重启操作
        if 'pod_name' in self.request.query_params.keys():
            name = self.request.query_params['pod_name']
            pods_obj = ProductionOprationPodsApi(namespace=namespace_name)
            return Response(pods_obj.restart_pods_api(pod_name=name))

        # 实例化分页类
        page_obj = ListPagination()

        # 通过deployment名称搜索对应的pods列表
        if 'searchName' in self.request.query_params.keys() and len(self.request.query_params['searchName']) > 0:
            from .utils.filter_search import FuzzMatching
            search_obj = FuzzMatching()
            search_name = self.request.query_params['searchName']
            pods_list = ProductionOprationPodsApi(namespace=namespace_name).get_pods_api()
            data = search_obj.matching(applications=pods_list, projectName=search_name)
            results = page_obj.paginate_queryset(queryset=data, request=request, view=self)
            return page_obj.get_paginated_response(results)

        # 获取所有pod列表
        pods_list = ProductionOprationPodsApi(namespace=namespace_name).get_pods_api()
        results = page_obj.paginate_queryset(queryset=pods_list, request=request, view=self)
        # 返回带超链接 需返回的时候用内置的响应方法
        return page_obj.get_paginated_response(results)


class ProductionDeploymentApiView(APIView):
    '''deployment'''

    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)

    def get(self, request, *args, **kwargs):
        '''获取对应命名空间的部署  传参：{'namespace_name':str}'''

        namespace_name = self.request.query_params['namespace_name']
        search_name = self.request.query_params['searchName']
        if len(namespace_name) <= 0:
            return Response({'msg': 'namespace_name为必传参数'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        page_obj = ListPagination()

        deployment_list = ProductionOprationDeploymentApi(namespace=namespace_name).get_deployment_api()
        results = page_obj.paginate_queryset(queryset=deployment_list, request=request, view=self)
        if search_name == 'null' or len(search_name) <= 0:
            return page_obj.get_paginated_response(results)

        from .utils.filter_search import FuzzMatching
        search_obj = FuzzMatching()
        data = search_obj.matching(applications=deployment_list, projectName=search_name)
        results = page_obj.paginate_queryset(queryset=data, request=request, view=self)
        return page_obj.get_paginated_response(results)

    def post(self, request, *args, **kwargs):
        '''创建应用'''
        namespace_name = request.data['namespace']
        application_name = request.data['name']
        application_port = request.data['port']
        application_tag = request.data['tag']
        deployment_replicas = request.data['replicas']
        domain_switch = request.data['switch']
        domain = request.data['domain']

        application_msg = []
        # 创建deployment
        deployment_obj = ProductionOprationDeploymentApi(
            tag=application_tag,
            port=application_port,
            namespace=namespace_name,
            deployment_name=application_name
        )
        service_obj = ProductionOprationServiceApi(
            namespace=namespace_name,
            service_name=application_name
        )
        ingress_obj = ProductionOprationIngressApi(
            namespace=namespace_name,
            ingress_name=application_name
        )
        # 创建deployment
        if application_name in deployment_obj.get_deployment_name_api():
            application_msg.append({'deployment_name': application_name, 'msg': '已存在'})
        else:
            deployment_obj.create_deployment_api(replicas=deployment_replicas)
            application_msg.append({'deployment_name': application_name, 'msg': '创建成功'})

        # 创建关联service
        if application_name in service_obj.get_service_name_api():
            application_msg.append({'service_name': application_name, 'msg': '已存在'})
        else:
            service_obj.create_service_api(port=application_port)
            application_msg.append({'service_name': application_name, 'msg': '创建成功'})

        # 创建关联ingress
        if application_name in ingress_obj.get_ingress_name_api():
            application_msg.append({'ingress_name': application_name, 'msg': '已存在'})
        else:
            if domain_switch is False:
                application_msg.append({'ingress_name': application_name, 'msg': '没有接收到域名'})
            else:
                ingress_obj.create_ingress_api(
                    service_name=application_name,
                    service_port=application_port,
                    domain=domain
                )
                application_msg.append({'ingress_name': application_name, 'msg': '创建成功'})

        return Response(application_msg)

    def delete(self, request, *args, **kwargs):
        '''删除deployment 传参: {'namespace_name':str,'deployment_name':str}'''

        namespace_name = self.request.query_params['namespace_name']
        deployment_name = self.request.query_params['deployment_name']

        deployment_delete_obj = ProductionOprationDeploymentApi(namespace=namespace_name,
                                                                deployment_name=deployment_name)
        return Response(deployment_delete_obj.delete_deployment_api())


class ProductionDeploymentUpdateApiView(APIView):
    '''发布'''

    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)

    def get(self, request, *args, **kwargs):
        '''发布  传参：{'namespace_name':str,'deployment_name':str,'port':int}'''

        namespace_name = self.request.query_params['namespace_name']
        deployment_name = self.request.query_params['deployment_name']
        deployment_port = self.request.query_params['port']
        push_obj = push_log.objects.filter(push_env=namespace_name, status=True, name=deployment_name).order_by(
            '-id').values().first()
        new_tag = push_obj.get('tag')

        deploy_obj = ProductionOprationDeploymentApi(namespace=namespace_name, deployment_name=deployment_name,
                                                     port=deployment_port, tag=new_tag)
        return Response(deploy_obj.update_deployment_api(update_type='update'))


class ProductionDeploymentRollBackListApiView(APIView):
    '''回滚'''

    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)

    def get(self, request, *args, **kwargs):
        '''获取回滚的数据,仅返回最近的10条记录,  传参：{'namespace_name':str,'deployment_name':str}'''

        namespace_name = self.request.query_params['namespace_name']
        deployment_name = self.request.query_params['deployment_name']
        deploy_obj = ProductionDeployRecord.objects.filter(env=namespace_name, name=deployment_name).order_by(
            '-id').values()[:10]
        serializer = ProductionDeployRecordDetail(deploy_obj, many=True)
        return Response(serializer.data)


# 测试用
from rest_framework import viewsets
from rest_framework import mixins
from .serializers import ProductionDeployRecordCreate


class TestCreateDeploymentRollBackListViewSet(viewsets.GenericViewSet, mixins.CreateModelMixin):
    queryset = ProductionDeployRecord.objects.all()
    serializer_class = ProductionDeployRecordCreate


class ProductionDeploymentRollBackApiView(APIView):
    '''回滚'''

    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)

    def get(self, request, *args, **kwargs):
        '''执行回滚操作, 传参：{'namespace_name':str,'deployment_name':str,'port':int,'tag':str}'''

        namespace_name = self.request.query_params['namespace_name']
        deployment_name = self.request.query_params['deployment_name']
        deployment_port = self.request.query_params['port']
        new_tag = self.request.query_params['tag']

        deploy_obj = ProductionOprationDeploymentApi(namespace=namespace_name, deployment_name=deployment_name,
                                                     port=deployment_port, tag=new_tag)
        return Response(deploy_obj.update_deployment_api(update_type='rollBack'))


class ProductionIngressApiView(APIView):
    '''Ingress'''

    permission_classes = (permissions.IsAuthenticated,)
    authentication_classes = (SessionAuthentication, JSONWebTokenAuthentication)

    def get(self, request, *args, **kwargs):
        '''执行回滚操作, 传参：{'namespace_name':str}'''

        namespace_name = self.request.query_params['namespace_name']
        search_name = self.request.query_params['searchName']
        if len(namespace_name) <= 0:
            return Response({'msg': 'namespace_name为必传参数'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        page_obj = ListPagination()

        ingress_list = ProductionOprationIngressApi(namespace=namespace_name).get_ingress_api()
        results = page_obj.paginate_queryset(queryset=ingress_list, request=request, view=self)
        if search_name == 'null' or len(search_name) <= 0:
            return page_obj.get_paginated_response(results)

        from .utils.filter_search import FuzzMatching
        search_obj = FuzzMatching()
        data = search_obj.matching(applications=ingress_list, projectName=search_name)
        results = page_obj.paginate_queryset(queryset=data, request=request, view=self)
        return page_obj.get_paginated_response(results)

    def post(self, request, *args, **kwargs):
        '''创建Ingress'''

        ingress_name = request.data['ingress_name']
        namespace_name = request.data['namespace_name']
        service_name = request.data['service_name']
        service_port = request.data['service_port']
        domain = request.data['domain']

        ingress_obj = ProductionOprationIngressApi(namespace=namespace_name, ingress_name=ingress_name)
        return Response(
            ingress_obj.create_ingress_api(service_name=service_name, service_port=service_port, domain=domain))

    def delete(self, request, *args, **kwargs):
        '''删除deployment 传参: {'namespace_name':str,'deployment_name':str}'''

        namespace_name = self.request.query_params['namespace_name']
        ingress_name = self.request.query_params['ingress_name']

        ingress_delete_obj = ProductionOprationIngressApi(namespace=namespace_name, ingress_name=ingress_name)
        return Response(ingress_delete_obj.delete_ingress_api())


class ProductionServiceApiView(APIView):
    '''service'''

    def get(self, request, *args, **kwargs):
        '''获取服务列表 传参: {'namespace_name':str,'serarchName':str}'''

        namespace_name = self.request.query_params['namespace_name']
        search_name = self.request.query_params['searchName']
        if len(namespace_name) <= 0:
            return Response({'msg': 'namespace_name为必传参数'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        page_obj = ListPagination()

        service_list = ProductionOprationServiceApi(namespace=namespace_name).get_service_api()
        results = page_obj.paginate_queryset(queryset=service_list, request=request, view=self)
        if search_name == 'null' or len(search_name) <= 0:
            return page_obj.get_paginated_response(results)

        from .utils.filter_search import FuzzMatching
        search_obj = FuzzMatching()
        data = search_obj.matching(applications=service_list, projectName=search_name)
        results = page_obj.paginate_queryset(queryset=data, request=request, view=self)
        return page_obj.get_paginated_response(results)

    def post(self, request, *args, **kwargs):
        '''创建service  传参：{'namespace_name':str,'service_name':str,'service_port':int}'''

        namespace_name = request.data['namespace_name']
        service_name = request.data['service_name']
        service_port = request.data['service_port']

        service_obj = ProductionOprationServiceApi(namespace=namespace_name, service_name=service_name)
        return Response(service_obj.create_service_api(port=service_port))

    def delete(self, request, *args, **kwargs):
        '''删除service  传参：{'namespace_name':str,'service_name':str}'''

        namespace_name = self.request.query_params['namespace_name']
        service_name = self.request.query_params['service_name']

        service_obj = ProductionOprationServiceApi(namespace=namespace_name, service_name=service_name)
        return Response(service_obj.delete_service_api())
